﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BitPortal.Models;
using System.Linq.Expressions;
using BitPortal.Utils;

namespace BitPortal.Business
{
    public static partial class ArticleBLL
    {
        /// <summary>
        /// Lay duong link da Rewrite
        /// </summary>
        /// <param name="cat"></param>
        /// <returns></returns>
        public static string GetSEOUrl(this Article art)
        {
            return "/Article/" + art.ArticleCategory.Name.ToSeoString() + "/" + art.Title.ToSeoString() + "-ad" + art.ArticleID + ".aspx";
        }
        public static string GetSEOUrl(object title, object Id)
        {
            return "/Article/" + title.ToString().ToSeoString() + "-ad" + Id + ".aspx";
        }

        /// <summary>
        /// Xoa bai viet truc tiep
        /// </summary>
        /// <param name="article"></param>
        /// <returns></returns>
        public static int DeletePermanently(long articleID)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            Article article = bitEnt.Articles.SingleOrDefault(a => a.ArticleID == articleID);
            if (article != null)
            {
                Statistic statistic = article.Statistic;
                DiscussionGroup discussionGroup = article.DiscussionGroup;
                bitEnt.Articles.DeleteObject(article);
                //Delete Statistic
                if (statistic != null)
                {
                    bitEnt.Statistics.DeleteObject(statistic);
                }
                //Delete DiscussionGroup
                if (discussionGroup != null)
                {
                    bitEnt.DiscussionGroups.DeleteObject(discussionGroup);
                }
                return bitEnt.SaveChanges();
            }
            return 0;

        }

        /// <summary>
        /// Xoa tam thoi (dat IsDeleted = true)
        /// </summary>
        /// <param name="articleID"></param>
        /// <returns></returns>
        public static int Delete(long articleID)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            Article a = bitEnt.Articles.SingleOrDefault(ent => ent.ArticleID == articleID);
            a.IsDeleted = true;
            return bitEnt.SaveChanges();
        }

        /// <summary>
        /// Them bai viet
        /// </summary>
        /// <param name="article"></param>
        /// <returns></returns>
        public static int Insert(this Article article)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            //Add Static
            Statistic statistic = new Statistic() { DatetimeLastModified = DateTime.Now, ViewUserIDs = "#", ViewUserIPs = "#", LikeUserIDs = "#", DislikeUserIDs = "#" };
            bitEnt.Statistics.AddObject(statistic);
            //Add Discusstion
            DiscussionGroup discussionGroup = new DiscussionGroup() { DatetimeCreated = DateTime.Now, LanguageCode = article.LanguageCode, DiscussionCount = 0 };
            bitEnt.DiscussionGroups.AddObject(discussionGroup);
            //Add Article
            article.Statistic = statistic;
            article.DiscussionGroup = discussionGroup;
            bitEnt.Articles.AddObject(article);
            return bitEnt.SaveChanges();
        }

        /// <summary>
        /// Tra ve tat ca cac bai viet
        /// </summary>
        /// <returns></returns>
        public static IQueryable<Article> GetAll()
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            var list = from ent in bitEnt.Articles
                       where ent.IsDeleted == false
                       orderby ent.SortOrder descending, ent.ArticleID descending
                       select ent;
            return list;
        }

        /// <summary>
        /// Lay ra bai viet theo ID truyen vao
        /// </summary>
        /// <param name="articleID"></param>
        /// <returns></returns>
        public static Article GetByID(long articleID)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            return bitEnt.Articles.SingleOrDefault(ent => ent.ArticleID == articleID);
        }

        /// <summary>
        /// Lay ra danh sach bai viet theo tham so truyen vao
        /// </summary>
        /// <param name="languageCode"></param>
        /// <param name="title"></param>
        /// <param name="tags"></param>
        /// <param name="categoryID"></param>
        /// <param name="haveVideo"></param>
        /// <param name="havePhoto"></param>
        /// <param name="groupname"></param>
        /// <param name="isApproved"></param>
        /// <param name="isHot"></param>
        /// <param name="allowCommment"></param>
        /// <param name="isAnonymousePost"></param>
        /// <param name="isEnabled"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static IQueryable<Article> GetByCondition(string languageCode = null, string title = null, string tags = null, int? categoryID = null,
            bool? haveVideo = null, bool? havePhoto = null, string groupname = null, bool? isApproved = null, bool? isHot = null, bool? allowCommment = null
            , bool? isAnonymousePost = null, bool? isEnabled = null, int start = -1, int limit = -1, string sort = null, string dir = null)
        {
            var list = GetAll().Where(ent => (languageCode == null || ent.LanguageCode.Equals(languageCode)) &&
                    (title == null || ent.Title.Contains(title)) &&
                    (tags == null || ent.Tags.Contains(tags)) &&
                    (categoryID == null || ent.CategoryID == categoryID) &&
                    (haveVideo == null || ent.HaveVideo == haveVideo) &&
                    (havePhoto == null || ent.HavePhoto == havePhoto) &&
                    (groupname == null || ent.GroupName.Contains(groupname)) &&
                    (isApproved == null || ent.IsApproved == isApproved) &&
                    (isHot == null || ent.IsHot == isHot) &&
                    (allowCommment == null || ent.AllowComment == allowCommment) &&
                    (isAnonymousePost == null || ent.IsAnonymousePost == isAnonymousePost) &&
                    (isEnabled == null || ent.IsEnabled == isEnabled)
                );

            //Start Sorting
            if (sort != null)
            {
                var param = Expression.Parameter(typeof(Article), "ent");
                var sortExpression = Expression.Lambda<Func<Article, object>>(Expression.Property(param, sort), param);
                if (dir == "DESC")
                {
                    list = list.OrderByDescending(sortExpression);
                }
                else
                {
                    list = list.OrderBy(sortExpression);
                }
            }
            //Start Paging
            if (start >= 0 && limit > 0)
            {
                list = list.Skip(start).Take(limit);
            }
            return list;
        }

        /// <summary>
        /// Get Article in current category and in all its child categories
        /// </summary>
        /// <param name="categoryID"></param>
        /// <returns></returns>
        public static IQueryable<Article> GetByCategory(int categoryID)
        {
            List<Article> results = new List<Article>();
            ArticleCategory ac = ArticleCategoryBLL.GetByID(categoryID);
            if (ac != null)
            {
                results = GetAll().Where(ent => ent.CategoryID == categoryID).ToList();
                List<ArticleCategory> listChilds = new List<ArticleCategory>();
                ac.GetAllChilds(listChilds);
                foreach (ArticleCategory child in listChilds)
                {
                    var resultOfChild = GetAll().Where(ent => ent.CategoryID == child.CategoryID).ToList();
                    results = results.Union(resultOfChild).ToList();
                }
            }
            return results.AsQueryable();
        }

        public static IQueryable<Article> GetByCondition<T>(string languageCode = null, string title = null, string tags = null, int? categoryID = null,
            bool? haveVideo = null, bool? havePhoto = null, string groupname = null, bool? isApproved = null, bool? isHot = null, bool? allowCommment = null
            , bool? isAnonymousePost = null, bool? isEnabled = null, int start = -1, int limit = -1, string sort = "SortOrder", string dir = "DESC", IQueryable<Article> fromSource = null, bool searchFromChilds = true)
        {
            if (fromSource == null) fromSource = GetAll();
            if (searchFromChilds && categoryID != null)
            {
                fromSource = GetByCategory((int)categoryID);
                categoryID = null;
            }
            var list = fromSource.Where(ent => (languageCode == null || ent.LanguageCode.Equals(languageCode)) &&
                    (title == null || ent.Title.Contains(title)) &&
                    (tags == null || ent.Tags.Contains(tags)) &&
                    (categoryID == null || ent.CategoryID == categoryID) &&
                    (haveVideo == null || ent.HaveVideo == haveVideo) &&
                    (havePhoto == null || ent.HavePhoto == havePhoto) &&
                    (groupname == null || ent.GroupName.Contains(groupname)) &&
                    (isApproved == null || ent.IsApproved == isApproved) &&
                    (isHot == null || ent.IsHot == isHot) &&
                    (allowCommment == null || ent.AllowComment == allowCommment) &&
                    (isAnonymousePost == null || ent.IsAnonymousePost == isAnonymousePost) &&
                    (isEnabled == null || ent.IsEnabled == isEnabled)
                );

            //Start Sorting
            if (sort != null)
            {
                if (sort != "ArticleID")
                {
                    var param = Expression.Parameter(typeof(Article), "ent");
                    var sortExpression = Expression.Lambda<Func<Article, T>>(Expression.Property(param, sort), param);
                    if (dir == "DESC")
                    {
                        list = list.OrderByDescending(sortExpression).ThenByDescending(ent => ent.ArticleID);
                    }
                    else
                    {
                        list = list.OrderBy(sortExpression).ThenByDescending(ent => ent.ArticleID);
                    }
                }
                else
                {
                    if (dir == "DESC")
                    {
                        list = list.OrderByDescending(ent => ent.ArticleID);
                    }
                    else
                    {
                        list = list.OrderBy(ent => ent.ArticleID);
                    }
                }
            }
            //Start Paging
            if (start >= 0 && limit > 0)
            {
                list = list.Skip(start).Take(limit);
            }
            return list;
        }


        /// <summary>
        /// Seach fulltext tren bang nay, dat saveKeyWord = true de luu key word vao DB
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="saveKeyWord"></param>
        /// <returns></returns>
        public static List<Article> FulltextSearch(string keyword, bool saveKeyWord = true, bool addvanceSearch = true)
        {
            BitPortalEntities bitEnt = new BitPortalEntities();
            return (from a in bitEnt.Articles
                    join r in FulltextSearchID(keyword, saveKeyWord, addvanceSearch) on a.ArticleID equals r
                    select a).ToList();
        }

        public static List<Int64?> FulltextSearchID(string keyword, bool saveKeyWord = true, bool addvanceSearch = true)
        {
            BitPortalEntities bitEnt = new BitPortalEntities();
            List<Int64?> result = bitEnt.BitPortal_FT_Articles(keyword).ToList();
            if (addvanceSearch)
            {
                var keys = KeyWordBLL.ListSameKeyWord(keyword);
                foreach (string key in keys)
                {
                    result = result.Union(FulltextSearchID(key, false, false)).ToList();
                }
            }
            if (saveKeyWord)
            {
                (new Keyword() { KeyName = keyword, ResultCount = result.Count }).Save();
            }
            return result;
        }

    }
}